/*Author:S.Genikhov
Creatin Date:
Last modified:11/Sept/2010
Reviewed by :

Version 3 with possiblitiest to : Login,get,Bye and simple Security check.
Support only TCP connection.

Short project description:
Bases reallisation of FTP server command like : cd ,send recieve file and commands,
by using of state machine*/

#include <assert.h>
#include <string.h>
#include <unistd.h>

#include "internalftpserver.h"

#ifdef _DEBUG_FTP_HEADERREAD
#define FILECONDITION   if(header.u_FTPbitfild.FTPUnionHeader.m_iscommand == FILE_M) { clptr-> m_modes = FILE_M;  return header.u_FTPbitfild.FTPUnionHeader.m_datasize;} \
                         else { \
                            fprintf(stderr,"\nUnderfined case HeaderFunc line :%d \n", __LINE__);\
                            sleep(1);\
                         }

#else
#define FILECONDITION
#endif /*_DEBUG_FTP_HEADERREAD*/

#define DEADBEAF            ((void*)0xdeadbeef)



/*********CallBackFunction for generic server************************************************/

size_t Headrfunc(void* _packet,int _idclient,void* _attribut)
{
    FTPattr*            attr;
    FTPcln*             clptr;
    FTPHead             header;

    assert(_packet);
    assert(_attribut);

    attr = (FTPattr*) _attribut;

    clptr = FTPGetClientStruct(_idclient, attr);
    FTPReadHeadr( _packet,OUT &header);

    /*Sequrity check of lenght*/
    if(header.u_FTPbitfild.FTPUnionHeader.m_iscommand == COMMAND_C && header.u_FTPbitfild.FTPUnionHeader.m_datasize  > MAXPROMTLENGH)
    {
        FTPServerRespond(attr,FTP_ILIGAL_COMND,0);

        /*change client status in ftp*/
        clptr-> m_isDropMessage = DROP_MES;
        return 0; /* Client will be disconnect, it i wan't to disconnect him the return value has to be more than 0*/
    }

    if(header.u_FTPbitfild.FTPUnionHeader.m_iscommand == COMMAND_C && header.u_FTPbitfild.FTPUnionHeader.m_datasize<= MAXPROMTLENGH)
    {
        /*change client status*/
        clptr-> m_modes = COMND_M;
        return header.u_FTPbitfild.FTPUnionHeader.m_datasize;
    }

    FILECONDITION;
#ifndef _DEBUG_FTP_HEADERREAD
     clptr-> m_modes = FILE_M;
#endif /*_DEBUG_FTP_HEADERREAD*/
    return header.u_FTPbitfild.FTPUnionHeader.m_datasize;
}

/*New client conects creates its struct and insert into tree*/
void NewClient(int _idclient,void* _attribut)
{
    FTPcln*    cl;

    assert(_attribut);
    cl = (FTPcln*) malloc (sizeof(FTPcln));

    if (cl == 0)
    {
        perror("malloc :");
        fprintf(stderr,"Problems with new client allocantion line : %d, file :%s\n", __LINE__,__FILE__);
        return;
    }

    cl->m_pwdirect = (char*)malloc(2);
    if (cl->m_pwdirect == 0)
    {
        perror("malloc :");
        fprintf(stderr,"Problems with new client allocantion line : %d, file :%s\n", __LINE__, __FILE__);
        free (cl);
        return;
    }

    cl->m_pwdirect[0]='/'; cl->m_pwdirect[1]=0;

    cl->m_key=_idclient;
    cl->m_login = 0;

    cl->m_modes=COMND_M;
    cl->m_state=USER_S;
    cl->m_isDropMessage = NOTDROP_MES;

   BinTreeInsert(((FTPattr*) _attribut)->m_ft->m_Clients, cl);
/*TODO *Send invite message to new Client*/
   return;
}


void NewMessage(int _IDclient,void* _app, void*  _buf,size_t _mesSize)
{
    FTPcln*             clptr;
    assert(_app);

    clptr = FTPGetClientStruct(_IDclient,_app);



    if(clptr && clptr->m_isDropMessage)
    {
        return;
    }
    ((FTPattr*) _app)->m_cl = clptr;
    ((FTPattr*)_app)-> m_ft->m_ModeFunc[clptr->m_modes](_app,_buf,_mesSize);
    return;
}

void NewExeption(int _IDclient,void* _app, void*  _buf,size_t _mesSize)
{

}

void ClientDiscn(int _idclient,void* _atr,size_t _notreaded)
{
    FTPcln              cl;
    FTPcln*             clptr;
    BTreeIt            clientItr;



    cl.m_key = _idclient;
    clientItr = BinTreeFind(((FTPattr*)_atr)->m_ft->m_Clients,&_idclient);
    if (clientItr == BinTreeEnd(((FTPattr*)_atr)->m_ft->m_Clients) )
    {
        fprintf(stderr,"Client not found line :%d ",__LINE__);
        return;
    }

    clptr =(FTPcln*)BinTreeGetData(clientItr);
    BinTreeRemove(((FTPattr*)_atr)->m_ft->m_Clients,clientItr);
    free(clptr->m_pwdirect);
    free(clptr);

#ifdef _unitest_ftp_server_
    clptr=DEADBEAF;
#endif /*_unitest_ftp_server_   */
    return;
}





